﻿using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using System.IO;
using System.Collections.Generic;
using System;

namespace PenguinForce.Levels
{
    public class Grid
    {
        public Grid(Texture2D nullTexture, List<Texture2D> textureList)
        {
            m_nullTexture = nullTexture;
            m_textureList = textureList;
            m_grid = new Tile[WIDTH, HEIGHT];
            for (int i = 0; i < WIDTH; i++)
            {
                for (int j = 0; j < HEIGHT; j++)
                {
                    m_grid[i, j] = new Tile(textureList);
                }
            }
            m_startLocation = new Vector2(-1, -1);
            m_finishLocation = new Vector2(-1, -1);
            m_bearStartList = new List<Vector2>();
            fadingLayers = new List<FadingLayer>();
            m_parPenguins = 0;
            m_startingPenguins = 0;
        }

        public void AddFadingLayer(FadingLayer layer)
        {
            fadingLayers.Add(layer);
        }

        public void PlaceStartFlag(int x, int y)
        {
            m_startLocation.X = x * GRID_SIZE + GRID_SIZE / 2;
            m_startLocation.Y = y * GRID_SIZE + GRID_SIZE / 2;
        }

        public void PlaceFinishFlag(int x, int y)
        {
            m_finishLocation.X = x * GRID_SIZE + GRID_SIZE / 2;
            m_finishLocation.Y = y * GRID_SIZE + GRID_SIZE / 2;
        }

        public void PlaceBear(int x, int y)
        {
            Vector2 newBear = new Vector2(x * GRID_SIZE + GRID_SIZE / 2, y * GRID_SIZE + GRID_SIZE / 2);
            if (!m_bearStartList.Contains(newBear))
            {
                m_bearStartList.Add(newBear);
            }
        }

        public float GetFriction(Vector2 position)
        {

            int gridX = (int)position.X / 32;
            int gridY = (int)position.Y / 32;

            foreach (FadingLayer fading in fadingLayers)
            {
                foreach (Tile tile in fading.m_tiles)
                {
                    if (position.X >= tile.m_location.X && position.X < tile.m_location.X + 32
                        && position.Y >= tile.m_location.Y && position.Y < tile.m_location.Y + 32)
                    {
                        return tile.GetFriction();
                    }
                }
            }

            return m_grid[gridX, gridY].GetFriction();
        }
        public void ClearBears()
        {
            m_bearStartList = new List<Vector2>();
        }

        public void Update(GameTime gameTime)
        {

            foreach (FadingLayer fading in fadingLayers)
            {
                fading.Update(gameTime);
            }
            int i = 0;
            while (i < fadingLayers.Count)
            {
                if (fadingLayers[i].HasExpired())
                {
                    fadingLayers.Remove(fadingLayers[i]);
                }
                else
                {
                    i++;
                }
            }
        }

        public void Draw(GameTime gameTime, SpriteBatch sprite, Vector2 scroll)
        {
            DrawGrid(sprite, scroll);
            for (int i = 0; i < WIDTH; i++)
            {
                for (int j = 0; j < HEIGHT; j++)
                {
                    m_grid[i, j].Draw(gameTime, sprite, i * 32 - (int)scroll.X / 2, j * 32 - (int)scroll.Y / 2);
                }
            }


            foreach (FadingLayer fading in fadingLayers)
            {
                fading.Draw(sprite, gameTime);
            }
            //DrawBears(sprite, scroll);
            DrawFlags(sprite, scroll);

        }

        private void DrawFlags(SpriteBatch sprite, Vector2 scroll)
        {
            if (m_startLocation.X != -1 && m_startLocation.Y != -1)
            {
                sprite.Draw(m_startFlagTexture, new Vector2(m_startLocation.X - (int)scroll.X / 2, m_startLocation.Y - (int)scroll.Y / 2), new Rectangle(0, 0, 128, 128), Color.White, 0.0f, new Vector2(64, 128), 1.0f, SpriteEffects.None, 1.0f);
            }
            if (m_finishLocation.X != -1 && m_finishLocation.Y != -1)
            {
                sprite.Draw(m_finishFlagTexture, new Vector2(m_finishLocation.X - (int)scroll.X / 2, m_finishLocation.Y - (int)scroll.Y / 2), new Rectangle(0, 0, 128, 128), Color.White, 0.0f, new Vector2(64, 128), 1.0f, SpriteEffects.None, 1.0f);
            }
        }

        private void DrawBears(SpriteBatch sprite, Vector2 scroll)
        {
            foreach (Vector2 position in m_bearStartList)
            {
                sprite.Draw(m_bearStartTexture, new Vector2(position.X - (int)scroll.X / 2, position.Y - (int)scroll.Y / 2), new Rectangle(0, 0, 64, 64), Color.White, 0.0f, new Vector2(32, 64), 1.0f, SpriteEffects.None, 1.0f);
            }
        }

        private void DrawGrid(SpriteBatch sprite, Vector2 scroll)
        {
            for (int y = 0; y < HEIGHT; y++)
            {
                for (int x = 0; x < WIDTH; x++)
                {

                    Rectangle dest = new Rectangle();
                    dest.X = (x * 32) - (int)scroll.X / 2;
                    dest.Y = (y * 32) - (int)scroll.Y / 2;
                    dest.Width = 32;
                    dest.Height = 32;

                    if (x < WIDTH - 1)
                    {
                        sprite.Draw(m_nullTexture, new Rectangle(dest.X, dest.Y, 32, 1), new Color(255, 0, 0, 100));
                    }
                    if (y < HEIGHT - 1)
                    {

                        sprite.Draw(m_nullTexture, new Rectangle(dest.X, dest.Y, 1, 32), new Color(255, 0, 0, 100));
                    }

                    if (x < WIDTH - 1 && y < HEIGHT - 1)
                    {
                        sprite.Draw(m_nullTexture, dest, new Color(255, 0, 0, 100));

                    }

                }
            }
        }

        public void Save(String path)
        {
            System.IO.BinaryWriter writer = new System.IO.BinaryWriter(File.Open(@"data/" + path + ".pgn", FileMode.Create));

            writer.Write(GRID_SIZE);
            writer.Write(Width);
            writer.Write(Height);
            writer.Write(m_startLocation.X);
            writer.Write(m_startLocation.Y);
            writer.Write(m_finishLocation.X);
            writer.Write(m_finishLocation.Y);

            writer.Write(m_bearStartList.Count);
            foreach (Vector2 bearPosition in m_bearStartList)
            {
                writer.Write(bearPosition.X);
                writer.Write(bearPosition.Y);
            }

            for (int i = 0; i < WIDTH; i++)
            {
                for (int j = 0; j < HEIGHT; j++)
                {
                    writer.Write((int)m_grid[i, j].m_tileType);

                }
            }

            writer.Close();

        }

        public void Load(String path)
        {
            System.IO.BinaryReader reader = new System.IO.BinaryReader(File.Open(@"data/" + path + ".pgn", FileMode.Open));
            m_bearStartList = new List<Vector2>();

            reader.ReadInt32();
            reader.ReadInt32();
            reader.ReadInt32();

            m_startLocation = new Vector2(reader.ReadSingle(), reader.ReadSingle());
            m_finishLocation = new Vector2(reader.ReadSingle(), reader.ReadSingle());

            int count = reader.ReadInt32();

            for (int i = 0; i < count; i++)
            {
                m_bearStartList.Add(new Vector2(reader.ReadSingle(), reader.ReadSingle()));
            }

            for (int i = 0; i < WIDTH; i++)
            {
                for (int j = 0; j < HEIGHT; j++)
                {
                    m_grid[i, j].m_tileType = (Tile.TileTypes)reader.ReadInt32();

                }
            }

            reader.Close();
        }

        public bool OnGrid(int x, int y)
        {
            if (x >= 0 && x < WIDTH && y >= 0 && y < HEIGHT)
            {
                return true;
            }
            return false;
        }

        public int Width
        {
            get
            {
                return WIDTH;
            }
        }

        public int Height
        {
            get
            {
                return HEIGHT;
            }
        }

        public int GRIDSIZE
        {
            get
            {
                return GRID_SIZE;
            }

        }

        public const int GRID_SIZE = 32;
        public const int WIDTH = 200;
        public const int HEIGHT = 200;

        public Tile[,] m_grid;

        public Vector2 m_startLocation;
        public Vector2 m_finishLocation;

        public List<Vector2> m_bearStartList;

        private Texture2D m_nullTexture;
        public Texture2D m_startFlagTexture;
        public Texture2D m_finishFlagTexture;
        public Texture2D m_bearStartTexture;

        public List<Texture2D> m_textureList;


        private List<FadingLayer> fadingLayers;

        public int m_startingPenguins;
        public int m_parPenguins;
    }
}